home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 245_01 / lca42.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-10-26  |  13.8 KB  |  435 lines

  1.  
  2. /* (4,2) linear cellular automaton    */
  3. /*                    */
  4. /* Reference:                */
  5. /*                    */
  6. /*    Kenneth E. Perry            */
  7. /*    Abstract Mathematical Art        */
  8. /*    BYTE                */
  9. /*    December, 1986            */
  10. /*    pages 181-192            */
  11.  
  12. /*    Copyright (C) 1987        */
  13. /*    Harold V. McIntosh        */
  14. /*    Gerardo Cisneros S.        */
  15.  
  16. /* G. Cisneros, 4.3.87 */
  17. /* 10 April 1987 - Adapted for second neighbors [HVM] */
  18. /* 25 April 1987 - Collection of sample rules [HVM] */
  19. /* 26 April 1987 - Multiple menus [HVM] */
  20. /* 28 April 1987 - version for XVI Feria de Puebla [HVM] */
  21.  
  22. # include <bdos.h>
  23.  
  24. # define COLGRAF     4  /* graph resolution */
  25. # define T80X25      3  /* text resolution */
  26. # define WHCYMAG     1  /* color quad for normal screen */
  27. # define AL        320  /* array length (screen width) */
  28. # define DS        16  /* number of distinct sums */
  29. # define NX         91    /* number of sample rules */
  30.  
  31. char xrule[] =
  32.  
  33.     "0000012233331111"  /* interesting background */
  34.     "0000021232311000"  /* nice gliders & 2-sided cycles */
  35.     "0000112232211000"  /* class iv stills */
  36.     "0000121232310000"  /* cycles */
  37.     "0000122313221000"  /* small black, big green blotches */
  38.  
  39.     "0001310000012100"  /* class iv w/zigzag */
  40.     "0010321000321010"  /* glider class iv dies */
  41.     "0010032000132011"  /* binary fission */
  42.     "0010102010332233"  /* slow red glider */
  43.     "0010132000231011"  /* */
  44.  
  45.     "0010230200100001"  /* small class iv periodic */
  46.     "0012030200100220"  /* localized */
  47.     "0010132000132011"  /* interesting binary fission */
  48.     "0013331303033023"  /* very delicate - blue background */
  49.     "0023111031322011"  /* dies quickly class iv */
  50.  
  51.     "0023323310033133"  /* more regular but delicate */
  52.     "0100002323111111"  /* red automaton various barriers */
  53.     "0100002232311111"  /* barriers and red (2,1) */
  54.     "0100010323212121"  /* interesting mixed */
  55.     "0100021121101101"  /* natural barriers */
  56.  
  57.     "0100021123301101"  /* strong & fragile barriers */
  58.     "0100320333033113"  /* good vs evil */
  59.     "0102220002123003"  /* noteworthy */
  60.     "0110001323211113"  /* cycles */
  61.     "0110013230203233"  /* blue vs red - striking */
  62.  
  63.     "0110031111222333"  /* blue-green split in red foreg. */
  64.     "0120330111101331"  /* also delicate */
  65.     "0010321000321010"  /* long period reflector - glider */
  66.     "0020013111222033"  /* glider on red background */
  67.     "0020221113030110"  /* a new style */
  68.  
  69.     "0100002323111001"  /* red systeb between barriers */
  70.     "0100002323211121"  /* more colorful */
  71.     "0100012222233300"  /* green and red */
  72.     "0100121233320000"  /* blue triangles w/red */
  73.     "0100122233331111"  /* crazy stripes */
  74.  
  75.     "0100211001022220"  /* stills & gliders, no blue */
  76.     "0100311022223330"  /* neat, try variations */
  77.     "0110012222233331"  /* green and red compete */
  78.     "0110122033301111"  /* even crazier stripes */
  79.     "0111003221022222"  /* rec w/other colors struggling */
  80.  
  81.     "0111003222102333"  /* variant w/blue cores /*
  82.     "0133333112111220"  /* bears looking at again */
  83.     "0200010323003133"  /* conflict of blue vs black */
  84.     "0200012303223303"  /* black vs blue */
  85.     "0200001323211112"  /* gliders and cycles */
  86.  
  87.     "0200122102233233"  /* unstable */
  88.     "0200110123123010"  /* class iv w/red background */
  89.     "0201212113312303"  /* delicate */
  90.     "0210012222223331"  /* big green and red compete */
  91.     "0220010323203233"  /* blue background w/cycl & glidr */
  92.  
  93.     "0230013022200303"  /* class iv on green */
  94.     "0230013022200313"  /* less prolific & dies out */
  95.     "0232020000100012"  /* green dominated by blue */
  96.     "0200211301023220"  /* black spots */
  97.     "0310020330100001"  /* interesting zigzag */
  98.  
  99.     "0310020101103102"  /* */
  100.     "0310020101103122"  /* jungle pyramids */
  101.     "0310102020230000"  /* still on green */
  102.     "0313320330100001"  /* */
  103.     "0310020101103122"  /* jungle pyramids */
  104.  
  105.     "0100211001022220"  /* stills and gliders */
  106.     "1002033112212122"  /* cycles on green background; slow glider */
  107.     "1200012222233000"  /* dying gliders & glider generator */
  108.     "1202000213121123"  /* gliders on striped background */
  109.     "1210012222233000"  /* also interesting - dying gliders */
  110.  
  111.     "1211133030313323"  /* glider on blue */
  112.     "1222330131213111"  /* another delicate */
  113.     "1222330131213113"  /* similar but jitters */
  114.     "2000013111213333"  /* blue glider on black */
  115.     "2013300233223300"  /* so-so cycles */
  116.  
  117.     "2110013112033331"  /* wedge diminishes to glider */
  118.     "2120320203223021"  /* glider & local */
  119.     "2120320203223023"  /* glider and local variant */
  120.     "2200013112033331"  /* variant */    
  121.     "2213331303033023"  /* delicate but more prolific */
  122.  
  123.     "2222003031000213"  /* green and black strips & stills */
  124.     "2222003031000210"  /* has a bouncing glider */
  125.     "2300013111213330"  /* macroscopic glider */
  126.     "2313113000001333"  /* vivid */
  127.     "2322022110002201"  /* stripey class iv */
  128.  
  129.     "3003003300123120"  /* class iv blue/black monochrome */
  130.     "3030111032310222"  /* class iv cycles - dies quickly */
  131.     "3031300300330012"  /* some triangle conflicts */
  132.     "3110220211131302"  /* chinese lantern */
  133.     "3100002022011123"  /* striking reiangles in matrix */
  134.  
  135.     "3120202022011123"  /* blue triangles in green matrix */
  136.     "3122320211331223"  /* pleasant */
  137.     "3223212330100010"  /* be patient - it regularizes */
  138.     "3312020131133323"  /* interesting barrier conflict */
  139.     "3320001132030011"  /* 3 color cycle w/glider */
  140.  
  141.     "2332212222200001"  /* triangles */
  142.  
  143.     ;
  144.  
  145. char  xx[4], rule[DS+1];
  146. int   arule[DS], arr1[AL], arr2[AL];
  147.  
  148. main()
  149. {
  150. int c, i, jj, n;
  151. int  more = 'r';
  152.  
  153.     videopalette(WHCYMAG);                /* white/cyan/magenta */
  154.  
  155.     tuto();
  156.     while (!kbdst()) jj=rand();                /* wait for keypress */
  157.     c=kbdin();                        /* ignore it */
  158.     jj=rand()%NX;
  159.     for (i=0; i<DS; i++) rule[i] = xrule[DS*jj+i];    /* random sample rule */
  160.     rule[DS]=0;
  161.     for (i=0; i<AL; i++) {                /* random initial array */
  162.     if (i%4 == 0) c=rand();
  163.     arr1[i]=c&3; c>>=2;};
  164.     videomode(T80X25);
  165.     videoscroll(3,0,4,71,0,3);                /* menu on blue background */
  166.     videoscroll(16,0,21,71,0,3);
  167.     xmenu(jj+1);                    /* show initial rule */
  168.  
  169.     while (more!='n') {                    /* execute multiple runs */
  170.     rmenu();
  171.     lmenu();
  172.     while (0<1) {                    /* set up one run */
  173.     c=kbdin();
  174.     if (c=='g') break;                    /* go draw graph */
  175.     if (c=='q') more='n';                /* quit for good */
  176.     if (more=='n') break;
  177.     switch (c) {
  178.         case 'r':                    /* edit rule */    
  179.         xblnk();
  180.         edrule();
  181.         videocursor(0,3,0);
  182.         rmenu();
  183.         break;
  184.         case 'l':                    /* edit cell string */
  185.         xblnk();
  186.         edline();
  187.         videocursor(0,3,0);
  188.         lmenu();
  189.         break;
  190.         case '#':                    /* read stored rule */
  191.         xmenu(NX);
  192.         n=DS*((i=lim(1,numin(0),NX))-1);
  193.         xmenu(i);
  194.         for (i=0; i<DS; i++) rule[i] = xrule[n+i];
  195.         rmenu();
  196.             break;
  197.         case 'u':
  198.         xblnk();
  199.         for (i=0; i<AL; i++) arr1[i]=0;
  200.         arr1[AL/4]=1;
  201.             arr1[AL/2]=2;
  202.             arr1[(3*AL)/4]=3;
  203.         lmenu();
  204.             break;
  205.     case 'x':                    /* random rule */
  206.         xblnk();
  207.             for (i=0; i<DS; i++) {
  208.             if (i%4 == 0) c = rand();
  209.             rule[i] = '0'+(c & 3);
  210.             c >>= 2;
  211.             };
  212.         rmenu();
  213.         break;
  214.     case 'y':                    /* random line */
  215.         xblnk();
  216.         for (i=0; i<AL; i++) {
  217.             if (i%4 == 0) c = rand();
  218.             arr1[i] = c & 3;
  219.             c >>= 2;
  220.             };
  221.             lmenu();
  222.         break;
  223.         default: break;
  224.         };
  225.     };
  226.     if (more=='n') break;
  227.     do {
  228.     evolve(rule);
  229.     videocursor(0,0,0);
  230.     scrstr("More?");
  231.     videocursor(0,0,30);
  232.     scrstr("y/n/cr");
  233.     more=kbdin();
  234.     } while (more=='\015');
  235.     videomode(T80X25);                    /* reset the screen */
  236.     if (more=='n') break;
  237.     };
  238. }    
  239.  
  240. edrule()                        /* edit the rule */
  241. {
  242. char c;
  243. int  i;
  244.  
  245.     videocursor(0,1,6);                    /* get the rule */
  246.     i=0;
  247.     while (i<DS) {
  248.         videoputc(rule[i],2);
  249.         videoputc('\010',1);
  250.         c = kbdin();
  251.         if (c == '\015') break;
  252.         switch (c) {
  253.         case '0':  case '1': case '2': case '3':    /* state */
  254.             rule[i++] = c;
  255.             videoputc(c,1);
  256.             break;
  257.         case ' ':                    /* space = advance */
  258.             videoputc(rule[i++],1);
  259.             break;
  260.         case '\010':                    /* backspace */
  261.             if (i==0) break;
  262.             videoputc(rule[i--],1);
  263.             videoputc(c,1);
  264.             videoputc(c,1);
  265.             break;
  266.     default: break;
  267.         };
  268.     };
  269. }
  270.  
  271. edline() {                        /* edit the line */
  272.  
  273. char c;
  274. int  i, j, k, ii, jj;
  275.  
  276.     videocursor(0,16,0);
  277.     scrstr("insert states using 0, 1, 2, 3");
  278.     videocursor(0,17,0);
  279.     scrstr("move cursor with n(north), s(south), e(east), w(west), or");
  280.     videocursor(0,18,0);
  281.     scrstr("with keyboard arrows. Space, backspace move right and left.");
  282.     videocursor(0,19,0);
  283.     scrstr("( seeks left margin, < absolutely, { up one line, [ down one line");
  284.     videocursor(0,20,0);
  285.     scrstr(") seeks right margin, > absolutely, } up one line, ] down one line");
  286.     videocursor(0,21,0);
  287.     scrstr("carriage return exits");
  288.     jj=4;
  289.     ii=1;
  290.     while (0<1) {
  291.     ii=lim(1,ii,40);
  292.     jj=lim(1,jj,8);
  293.     j=jj-1;
  294.     i=ii-1;
  295.     videocursor(0,j+6,i);
  296.     c=kbdin();
  297.     if (c == '\015') {videoscroll(16,0,21,70,0,3); break;};
  298.     switch (c) {
  299.     case '0':  case '1': case '2': case '3':        /* enter  state */
  300.         arr1[40*j+i] = c-'0';
  301.     ii++;
  302.     break;
  303.     case 's': case '\012': case '\320':          jj++; break;    /* down - next line */
  304.     case 'n': case '\013': case '\310':          jj--; break;    /* up   - last line */
  305.     case 'e': case '\014': case '\315': case ' ': ii++; break;    /* space = advance  */
  306.     case 'w': case '\010': case '\313':          ii--; break;    /* backspace */
  307.     case '<': ii=1;  jj=1;  break;  /* absolute left */
  308.     case '{': ii=1;  jj--;  break;  /* left one row up */
  309.     case '(': ii=1;         break;  /* left this row */
  310.     case '[': ii=1;  jj++;  break;  /* left next row */
  311.     case '>': ii=40; jj=40; break;  /* absolute right */
  312.     case '}': ii=40; jj--;  break;  /* right one row up */
  313.     case ')': ii=40;        break;  /* right this row */
  314.     case ']': ii=40; jj++;  break;  /* right next row */
  315.     default: break;
  316.         };
  317.     videocursor(0,j+6,0);
  318.     for (k=0; k<40; k++) videoputc('0'+arr1[40*j+k],1);
  319.     };
  320. }
  321.  
  322. evolve(rule)                        /* display a screen of evolution */
  323. char *rule;
  324. {
  325. int i, j, sum, sum0, sum1, sum2, sum3;
  326.  
  327.     videomode(COLGRAF);                    /* erase the screen */
  328.     videocursor(0,0,0);                    /* top text line */
  329.     scrstr("Rule: ");
  330.     scrstr(rule);
  331.     for (i=0; i<DS; i++) {arule[i] = rule[i]-'0';}
  332.     for (j=8; j<200; j++) videodot(j,AL-1,2);
  333.     for (j=8; j<200; j++) {                /* evolve for 192 generations */
  334.         sum0 = arr1[AL-2] + arr1[AL-1] + arr1[0] + arr1[1] + arr1[2];
  335.         sum1 = arr1[AL-1] + arr1[0] + arr1[1] + arr1[2] + arr1[3];
  336.         arr2[0] = arule[sum0];
  337.         arr2[1] = arule[sum1];
  338.         for (i=2; i<AL-2; i++) {
  339.             sum = arr1[i-2] + arr1[i-1] + arr1[i] + arr1[i+1] + arr1[i+2];
  340.             arr2[i] = arule[sum];
  341.             };
  342.         sum2 = arr1[AL-3] + arr1[AL-2] + arr1[AL-1] + arr1[0] + arr1[1];
  343.         sum3 = arr1[AL-4] + arr1[AL-3] + arr1[AL-2] + arr1[AL-1] + arr1[0];
  344.         arr2[AL-1] = arule[sum2];
  345.         arr2[AL-2] = arule[sum3];
  346.         for (i=0;  i<AL; i++) {videodot(j,i,arr1[i]); arr1[i] = arr2[i];};
  347.     if (kbdst()) {kbdin(); break;};
  348.         }
  349. }
  350.  
  351. tuto()                            /* tutorial and Help screen */
  352. {
  353.     videomode(T80X25);
  354.     videocursor(0,2,0);
  355.     scrstr("<Copyright (C) 1987 - H.V. McIntosh, G. Cisneros S.>");
  356.     videocursor(0,4,0);
  357.     scrstr("        ***** LIFE in One Dimension *****");
  358.     videocursor(0,6,0);
  359.     scrstr("Four States - Black(0), Cyan(1), Magenta(2), White(3).");
  360.     videocursor(0,8,0);
  361.     scrstr("Second neighbors - two on each side, five altogether.");
  362.     videocursor(0,10,0);
  363.     scrstr("Totalistic transition rule - random, edited, or stored.");
  364.     videocursor(0,12,0);
  365.     scrstr("Initial Cellular Array - random, edited, or patterned.");
  366.     videocursor(0,14,0);
  367.     scrstr("Some rules are fragile and require several tries before");
  368.     videocursor(0,15,0);
  369.     scrstr("manifesting an interesting evolutionary pattern.");
  370.     videocursor(0,17,0);
  371.     scrstr("Use any key to terminate a display in progress.");
  372.     videocursor(0,21,0);
  373.     scrstr("now, press any key to continue ...");
  374. }
  375.  
  376. rmenu() {                        /* rule menu */
  377.     videocursor(0,0,0);
  378.     scrstr("      0....1....2....3");
  379.     videocursor(0,1,0);
  380.     scrstr("Rule: "); scrstr(rule);
  381.     videocursor(0,3,0);
  382.     scrstr("    r(rule), l(line), #nn(stored rule), g(graph), q(quit)");
  383.     videocursor(0,4,0);
  384.     scrstr("             x(random rule), y(random line), u(unit line).");
  385.     videocursor(0,3,0);
  386.     }
  387.  
  388. lmenu() {                        /* line menu */
  389. int i, j;
  390.     for (j=0; 40*j<AL; j++) {
  391.     videocursor(0,6+j,0);
  392.     for (i=0; i<40; i++) videoputc('0'+arr1[40*j+i],1);
  393.     }
  394.     videocursor(0,3,0);
  395.     }
  396.  
  397. xmenu(n) int n;                        /* display rule number */
  398. {int i, nn;  
  399.     nn=sprintf(xx,"%3d",n);
  400.     videocursor(0,1,30);
  401.     for (i=0; i<nn; i++) videoputc(xx[i],1);
  402.     videocursor(0,1,30);
  403. }
  404.  
  405. xblnk() {                        /* clear rule number */
  406.     videocursor(0,1,30);
  407.     scrstr("    ");
  408.     videocursor(0,3,0);
  409. }
  410.  
  411. int lim(i,j,k)
  412. int i, j, k;                        /* limit j to interval (i,k) */
  413.     {if (i>=j) return i; if (k<=j) return k; return j;}
  414.  
  415. scrstr(s)                        /* write a string in graphics mode */
  416. char *s;
  417. { for (; *s != '\0'; s++) videoputc(*s,1); }
  418.  
  419. int kbdst()                        /* keyboard status */
  420. {return(bdos(11) & 0xFF);}
  421.  
  422. kbdin() {                        /* direct keyboard input, no echo */
  423. int c;
  424.     if ((c = bdos(7) & 0xFF) == '\0') c = (bdos(7) & 0xFF) | 0x80;
  425.     return(c);
  426. }
  427.  
  428. int numin(n)                        /* read number from keyboard */
  429. int n; {char c;
  430.     c=kbdin();
  431.     if (c>='0'&&c<='9') return(numin(10*n+(c-'0'))); else return(n);
  432. }
  433.  
  434. /* end */
  435.